Skip to content

feat(book): documentation navigation spine + derived membership (ADR-0046 §6, P3a/P3b)#1879

Merged
xuyushun441-sys merged 4 commits into
mainfrom
feat/book-impl-p3a
Jun 15, 2026
Merged

feat(book): documentation navigation spine + derived membership (ADR-0046 §6, P3a/P3b)#1879
xuyushun441-sys merged 4 commits into
mainfrom
feat/book-impl-p3a

Conversation

@xuyushun441-sys

Copy link
Copy Markdown
Contributor

Implements the book navigation element specified in ADR-0046 §6 (merged in #1865).

Core idea — a spine, not a container

A book stores only an ordered spine (groups + audience + identity). Membership is derived from a rule on each group (include glob/tag) plus an optional scalar doc.order/doc.group — never a central pages array. This is the load-bearing choice (ADR §6.2.1):

  • AI safety: the AI creates a doc named to match a rule and it files itself — create-and-forget, no read-modify-write on a shared array.
  • Overlay safety: RFC 7396 merge-patch treats arrays atomically, so a central nav array would shadow package-added docs; a small derived spine + scalar order merges cleanly.

What's here

P3a — spec + resolver (@objectstack/spec)

  • BookSchema (spine), BookGroupSchema, BookNodeSchema, defineBook(); additive doc.order / doc.group.
  • resolveBookTree() — pure resolver: include glob/tag + explicit doc.group; explicit pages override (verbatim order, ---, ... rest, missing-doc, object nodes); unmatched docs → synthetic Uncategorized; first-group-wins dedup; package-scoped includes. deriveImplicitPackageBook() for the implicit per-package book.
  • Register book (render-time type, allowOrgOverride: true, loadOrder: 99); book → BookSchema in the type-schema map; stack.books; artifact field books → book.
  • 15 resolver/schema unit tests; spec tsc clean.

P3b — runtime + REST (@objectstack/objectql, @objectstack/rest, @objectstack/runtime)

  • Wire book/books through the runtime type enumerations (PLURAL_TO_SINGULAR, engine registerApp, app-plugin category keys).
  • REST GET /meta/book/:name/tree resolves the tree; read-layer audience gating (anonymous gets a book only when audience: 'public', else 401 — enforced in the read path, not just the UI).
  • Showcase ships a real showcase_manual book (audience public).

Verified live (artifact boot)

GET /api/v1/meta/book               → 1 item: showcase_manual
GET /api/v1/meta/book/showcase_manual/tree (anonymous)
  start         → showcase_index            (explicit pages)
  guides        → showcase_docs_guide       (DERIVED via include: "showcase_*_guide")
  uncategorized → setup_overview, studio_overview  (other-package docs, never dropped)
GET .../book/<unknown>/tree (anonymous)     → 401 (implicit org book is gated)

Known follow-up

  • The config-boot (os dev) serving path does not yet surface book items (artifact-boot os start does). The book registers into the boot engine but the env-scoped serving protocol reads a separate store whose enumeration still needs the type wired; tracked for a follow-up.
  • Portal UI (P3c) — the console docs sidebar + anonymous apps/docs ISR render live in the objectui/apps-docs surfaces (cross-repo); this PR delivers the backend the portal consumes.

🤖 Generated with Claude Code

os-zhuang and others added 4 commits June 15, 2026 10:27
…ved membership

Adds §6 to ADR-0046 specifying the P3 navigation model. A `book` is a metadata
element that stores only an ordered spine (groups); membership is derived by
rule (`include` glob/tag) plus optional per-doc `order`/`group`, never a central
array. This is chosen so AI authoring stays create-and-forget (no central-array
read-modify-write, §6.2.1) and runtime overlay stays merge-safe under RFC 7396.

Also specified: the implicit per-package book (packageId), `audience` access
(org / public≡guest / {profile}) enforced at the read layer, and a host-based
anonymous "library" portal reusing apps/docs (Fumadocs + per-host ISR) rather
than greenfield SSR. No `meta.json`: `book` is metadata, authored as *.book.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…p resolver (ADR-0046 §6, P3a)

- BookSchema (spine: ordered groups + audience + identity), BookGroupSchema,
  BookNodeSchema, defineBook(); additive scalar `doc.order` / `doc.group`.
- resolveBookTree(): pure derived-membership resolver — the AI-safety core. A
  doc joins a group by `include` glob/tag or explicit `doc.group`; explicit
  `pages` override (verbatim order, `---`, `...` rest, missing-doc, object
  nodes); unmatched docs → synthetic Uncategorized; first-group-wins dedup;
  package-scoped includes.
- deriveImplicitPackageBook(): the implicit per-package book (no "flat" fork).
- Register `book` metadata type (allowOrgOverride:true, loadOrder 99); artifact
  field `books` → `book`; `stack.books`.
- 15 resolver/schema tests; spec tsc clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…iring (ADR-0046 §6, P3b)

- REST `GET /meta/book/:name/tree` resolves a book spine against the docs that
  exist now into a rendered tree (resolveBookTree); unknown name → implicit
  per-package book. Read-layer `audience` gating: anonymous callers get a book
  only when its audience is `public` (else 401), enforced in the read path —
  not just the UI — since /meta reads are anonymous-reachable.
- Register `book` across the runtime metadata enumerations that were missing it:
  PLURAL_TO_SINGULAR (`books`→`book`), engine.registerApp metadataArrayKeys,
  app-plugin app-category keys, and the builtin type-schema map (book→BookSchema
  for Studio editing / diagnostics). Export `defineBook` from the spec root.
- Showcase ships a real `showcase_manual` book (audience: public) demonstrating
  explicit `pages` + `...` rest (start) and a derived `include` rule (guides).

Verified live (artifact boot): GET /meta/book → 1 item; /tree returns the
derived tree (guides filled by rule, other-package docs → Uncategorized);
public book serves anonymously (200), implicit org book is gated (401).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 15, 2026 6:24am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation protocol:system tests tooling size/xl labels Jun 15, 2026
@xuyushun441-sys
xuyushun441-sys merged commit 71578f2 into main Jun 15, 2026
13 checks passed
@xuyushun441-sys
xuyushun441-sys deleted the feat/book-impl-p3a branch June 15, 2026 06:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:system size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants